/*
 * 础光实时操作系统PhotonRTOS -- cpu功能支持
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <photon/bitops.h>
#include <photon/cpumask.h>
#include <photon/errno.h>
#include <photon/sched.h>
#include <photon/smp.h>
#include <photon/types.h>
#include <photon/cpu.h>
#include <asm/smp.h>
#include <asm/stack.h>

#include <asm/asm-offsets.h>
#include <asm/cputype.h>
#include <autosar/internal.h>

/**
 * 判断某个核上是否有任务被其它核异步激活的标志位。
 */
int32_t osek_core_if_activate[MAX_CPUS];

/**
 * 判断该核上是否有任务被其它核异步的设置了事件.
 */
int32_t osek_core_if_set_event[MAX_CPUS];

const DECLARE_BITMAP(cpu_all_bits, MAX_CPUS) = CPU_BITS_ALL;

static DECLARE_BITMAP(cpu_possible_bits, CONFIG_MAX_CPUS);
const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);


static DECLARE_BITMAP(cpu_online_bits, CONFIG_MAX_CPUS);
const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);


static DECLARE_BITMAP(cpu_present_bits, CONFIG_MAX_CPUS);
const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);


static DECLARE_BITMAP(cpu_active_bits, CONFIG_MAX_CPUS);
const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);

void mark_cpu_possible(uint32_t cpu, bool possible)
{
	if (possible) {
		cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits));
	} else {
		cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
	}
}

void mark_cpu_present(uint32_t cpu, bool present)
{
	if (present) {
		cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits));
	} else {
		cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));
	}
}

void mark_cpu_online(uint32_t cpu, bool online)
{
	if (online) {
		cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
	} else {
		cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
	}
}

void init_cpu_present(const struct cpumask *src)
{
	cpumask_copy(to_cpumask(cpu_present_bits), src);
}

void init_cpu_possible(const struct cpumask *src)
{
	cpumask_copy(to_cpumask(cpu_possible_bits), src);
}

void init_cpu_online(const struct cpumask *src)
{
	cpumask_copy(to_cpumask(cpu_online_bits), src);
}

struct slave_cpu_data slave_cpu_data;

static int32_t boot_secondary(uint32_t cpu, struct task_desc *idle)
{
	return arch_launch_cpu(cpu);
}

asmlinkage void start_slave(struct slave_cpu_data *slave_cpu_data)
{
	arch_start_slave(slave_cpu_data);

	BUG();
}

static int32_t __cpu_launch(uint32_t cpu, struct task_desc *idle)
{
	int32_t ret;
	pr_debug("准备启动核心：%d.\n", cpu);

	slave_cpu_data.stack = task_stack_bottom(idle) + THREAD_START_SP;
	slave_cpu_data.cpu = cpu;

	ret = boot_secondary(cpu, idle);
	if (ret == 0) {
		pr_info("CPU%d: success to boot: %d\n", cpu, ret);
	} else {
		pr_err("CPU%d: failed to boot: %d\n", cpu, ret);
	}


	return ret;
}

int32_t cpu_launch(uint32_t cpu)
{
	int32_t ret = 0;
	struct task_desc *idle = idle_task(cpu);

	if (cpu_online(cpu) || !cpu_present(cpu)) {
		ret = -EINVAL;
	} else {
		ret = __cpu_launch(cpu, idle);
	}

	return ret;
}

